/** @jsxImportSource @emotion/react */
import { HTMLAttributes, useState, type FC } from 'react';
import classNames from 'classnames';
import { animated, useSpring, useSpringRef } from '@react-spring/web';
import { useUpdateEffect } from 'react-use';
import { accordionContentDefaultProps } from './defaultProps';
import type { AccordionContentOptions } from './type';
import { useAccordionContext } from './AccordionContext';
import getStyleAttr from '../_util/getStyleAttr';

export interface AccordionContentProps extends AccordionContentOptions, Omit<HTMLAttributes<HTMLDivElement>, 'id'> {}

const AccordionContent: FC<AccordionContentProps> = (props) => {
  const { className, active, id, children, forwardedRef, style, ...accordionContentProps } = props;
  const [states, setStates] = useAccordionContext();
  const [css, setCss] = useState<any>(style);
  const [isActive, setIsActive] = useState(
    active || (states.exclusive ? states.activeId === id : states.activeIds.includes(id)),
  );
  const springRef = useSpringRef();

  const spring = useSpring({
    ref: springRef,
    height: 0,
    paddingTop: 0,
    paddingBottom: 0,
    marginTop: 0,
    marginBottom: 0,
    opacity: 0,
    config: { duration: states.duration },
  });

  useUpdateEffect(() => {
    if (states.inTransition && (states.prevId === id || (states.exclusive && states.activeId === id))) {
      setCss({ ...css, ...spring });
    } else {
      setCss(style);
    }
  }, [states.inTransition]);

  useUpdateEffect(() => {
    const el = document.getElementById(id.toString());
    const pt = Number(getStyleAttr(el, 'padding-top'));
    const pb = Number(getStyleAttr(el, 'padding-bottom'));
    const mt = Number(getStyleAttr(el, 'margin-top'));
    const mb = Number(getStyleAttr(el, 'margin-bottom'));

    if (states.exclusive ? states.activeId === id : isActive === false && states.activeIds.includes(id)) {
      setIsActive(true);
      setTimeout(() => {
        springRef.current.at(0)?.start({
          from: {
            height: 0,
            paddingTop: 0,
            paddingBottom: 0,
            marginTop: 0,
            marginBottom: 0,
            opacity: 0,
          },
          to: {
            height: (el?.scrollHeight || 0) + pt + pb + mt + mb,
            paddingTop: pt,
            paddingBottom: pb,
            marginTop: mt,
            marginBottom: mb,
            opacity: 1,
          },
          config: { duration: states.duration },
        });

        setTimeout(() => {
          if (states.exclusive) {
            setStates({ ...states, prevId: states.activeId, inTransition: false });
          } else {
            setStates({ ...states, prevId: id, inTransition: false });
          }
        }, (states.duration || 250) + 20);
      });
    } else {
      if (states.prevId === id) {
        springRef.current.at(0)?.start({
          from: {
            height: el?.scrollHeight ? el?.scrollHeight : 0,
            paddingTop: pt,
            paddingBottom: pb,
            marginTop: mt,
            marginBottom: mb,
            opacity: 1,
          },
          to: {
            height: 0,
            paddingTop: 0,
            paddingBottom: 0,
            marginTop: 0,
            marginBottom: 0,
            opacity: 0,
          },
          config: { duration: states.duration },
        });

        setTimeout(() => {
          setIsActive(false);
          if (states.exclusive) {
            setStates({ ...states, prevId: states.activeId, inTransition: false });
          } else {
            setStates({ ...states, prevId: id, inTransition: false });
          }
        }, (states.duration || 250) + 20);
      }
    }
  }, [states.activeId, states.activeIds]);

  return (
    <animated.div
      ref={forwardedRef}
      id={id.toString()}
      className={classNames(
        'content',
        {
          active: isActive,
          animating:
            (states.exclusive ? states.activeId === id || states.prevId === id : states.activeIds.includes(id)) &&
            states.inTransition,
        },
        className,
      )}
      style={css}
      css={{ overflow: states.inTransition ? 'hidden' : 'auto' }}
      {...accordionContentProps}
    >
      {children}
    </animated.div>
  );
};

AccordionContent.displayName = 'AccordionContent';
AccordionContent.defaultProps = accordionContentDefaultProps;

export default AccordionContent;
